[React] 副作用フックを使用してsetTimeoutのタイマーをリセットする
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、Reactアプリケーションで、副作用フック(useEffect)を使用してsetTimeoutのタイマーをリセットしてみました。
デモ
上記のサンドボックスを開いてから10秒経過後のコンソール出力。
TimerID 15 has started. 10 seconds has passed. TimerID 15 has finished.
続けてRestartボタンをクリックして10秒経過後のコンソール出力。
Restart button was clicked. TimerID 15 was canceled. TimerID 197 has started. 10 seconds has passed. TimerID 197 has finished.
コード概要
import React, { useState, useEffect } from 'react'; export const App: React.FC = () => { const [now, setNow] = useState(Date.now()); useEffect(() => { const timer = setTimeout(() => { //some action console.log( '10 seconds has passed. TimerID ' + String(timer) + ' has finished.' ); }, 10 * 1000); console.log('TimerID ' + String(timer) + ' has started.'); //クリーンアップ return () => { console.log( 'Restart button has clicked. TimerID ' + String(timer) + ' has canceled.' ); clearTimeout(timer); }; }, [now]); return ( <> <div> ・このページを開くと10秒のカウントが開始します。 </div> <div> ・カウントが完了すると「10 seconds has passed.」と出力されます。 </div> <div> ・Restartボタンをクリックすると、タイマーが0秒から再開始されます。以前のタイマーはキャンセルされます。 </div> <div> <button onClick={() => { setNow(Date.now()); }} > Restart </button> </div> </> ); };
- ページを開くと
useEffect
のコールバックが開始。(TimerID XX has started. と出力) - 10秒後に
setTimeout
のコールバックが実行。(10 seconds has passed.〜 と出力) - Restartボタンをクリックして
now
のステートを更新。 - 前回の
useEffect
のクリーンアップを実行。clearTimeout
される。(Restart button was clicked.〜 と出力) - 1〜4が繰り返される。
useEffectのクリーンアップを使用すると前回のコールバックの実行に対して指定の処理を実行できます。これを利用することにより前回のsetTimeoutのタイマーをキャンセルしつつ、次の新しいタイマーを開始することができます。
ちなみに
タイマーのリセットが不要であれば下記エントリでの実装のようにuseEffect
を使わずに実装することも可能です。
参考
以上